package cn.fintecher.pangolin.service.business.service;

import cn.fintecher.pangolin.common.enums.*;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.RepositoryUtil;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.BaseCase;
import cn.fintecher.pangolin.entity.elastic.PersonalAddress;
import cn.fintecher.pangolin.entity.elastic.PersonalContact;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.service.business.model.request.*;
import cn.fintecher.pangolin.service.business.model.response.PersonalAddressResponse;
import cn.fintecher.pangolin.service.business.model.response.PersonalContactResponse;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.BaseCaseRespository;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.PersonalAddressElastic;
import cn.fintecher.pangolin.service.business.repository.elasticsearch.PersonalContactElastic;
import cn.fintecher.pangolin.service.business.repository.jparepository.CaseInfoRepository;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 11:01 2019/9/16
 */

@Service("personalService")
@Transactional(rollbackFor = Exception.class)
public class PersonalService {
    @Autowired
    private PersonalContactElastic personalContactElastic;

    @Autowired
    private PersonalAddressElastic personalAddressElastic;

    @Autowired
    private BaseCaseRespository baseCaseRespository;

    @Autowired
    private ModelMapper modelMapper;

    @Autowired
    private BaseService baseService;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    /**
     * 查询客户联系人信息
     */
    public List<PersonalContactResponse> findPersonalContact(String caseId) {
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("caseId.keyword", caseId));
        Iterable<PersonalContact> iterable = personalContactElastic.search(builder);
        List<PersonalContact> list = IterableUtils.toList(iterable);
        list.sort((e1, e2) -> e2.getOperateTime().compareTo(e1.getOperateTime()));
        Type listType = new TypeToken<List<PersonalContactResponse>>() {
        }.getType();
        return modelMapper.map(list, listType);
    }

    /**
     * 查询客户地址信息
     */
    public List<PersonalAddressResponse> findPersonalAddress(String caseId) {
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("caseId.keyword", caseId));
        Iterable<PersonalAddress> iterable = personalAddressElastic.search(builder);
        List<PersonalAddress> list = IterableUtils.toList(iterable);
        list.sort((e1, e2) -> e2.getOperateTime().compareTo(e1.getOperateTime()));
        Type listType = new TypeToken<List<PersonalAddressResponse>>() {
        }.getType();
        return modelMapper.map(list, listType);
    }

    /**
     * 联系方式/地址状态标记有效无效
     */
    public void markStatus(MarkStatusRequest request, String token) {
        checkCase(request.getCaseId(), request.getCaseType());
        UserModel userModel = baseService.getUserByToken(token);
        if (Objects.equals(request.getFlag(), 0)) { //联系电话
            Iterable<PersonalContact> iterable = personalContactElastic.findAllById(request.getIds());
            iterable.forEach(e -> {
                e.setStatus(request.getStatus());
                e.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
            });
            personalContactElastic.saveAll(iterable);
        } else { //地址
            Iterable<PersonalAddress> iterable = personalAddressElastic.findAllById(request.getIds());
            iterable.forEach(e -> {
                e.setStatus(request.getStatus());
                e.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
            });
            personalAddressElastic.saveAll(iterable);
        }
    }

    /**
     * 新增联系人信息
     */
    public void addPersonalContact(AddContactRequest request, String token) {
        UserModel userModel = baseService.getUserByToken(token);
        List<PersonalContact> personalContacts = new ArrayList<>();
        BaseCase baseCase = baseCaseRespository.findById(request.getCaseId()).orElseThrow(() -> new BadRequestException(null, "baseCase", "case.is.null"));
        if (StringUtils.isNotBlank(request.getPhoneNo())) {
            PersonalContact personalContact = generatePersonalContact(request, baseCase, userModel, PhoneType.HOME_PHONE, request.getPhoneNo());
            personalContacts.add(personalContact);
        }
        if (StringUtils.isNotBlank(request.getMobile())) {
            PersonalContact personalContact = generatePersonalContact(request, baseCase, userModel, PhoneType.MOBILE, request.getMobile());
            personalContacts.add(personalContact);
        }
        if (StringUtils.isNotBlank(request.getWorkNo())) {
            PersonalContact personalContact = generatePersonalContact(request, baseCase, userModel, PhoneType.OFFICE_PHONE, request.getWorkNo());
            personalContacts.add(personalContact);
        }
        RepositoryUtil.saveData(personalContactElastic, personalContacts);
    }

    /**
     * 生成联系人
     */
    private PersonalContact generatePersonalContact(AddContactRequest request, BaseCase baseCase, UserModel userModel, PhoneType type, String phone) {
        checkCase(request.getCaseId(), request.getCaseType());
        PersonalContact personalContact = new PersonalContact();
        personalContact.setCaseId(request.getCaseId());
        personalContact.setCaseNumber(baseCase.getCaseNumber());
        personalContact.setPrincipalId(request.getPrincipalId());
        personalContact.setName(request.getName());
        personalContact.setCertificateNo(request.getCertificateNo());
        personalContact.setSource(request.processSource());
        personalContact.setRelation(request.processRelation());
        personalContact.setRemark(request.getRemark());
        personalContact.setType(type);
        personalContact.setPhoneNo(phone);
//        personalContact.setStatus(ContactStatus.EFFECTIVE);
        personalContact.setIsEnable(BaseStatus.ON);
        personalContact.process(userModel.getId(), ZWDateUtil.getNowDateTime(), true);
        return personalContact;
    }

    /**
     * 新增地址信息
     */
    public void addPersonalAddress(AddAddressRequest request, String token) {
        checkCase(request.getCaseId(), request.getCaseType());
        UserModel userModel = baseService.getUserByToken(token);
        List<PersonalAddress> list = new ArrayList<>();
        BaseCase baseCase = baseCaseRespository.findById(request.getCaseId()).orElseThrow(() -> new BadRequestException(null, "baseCase", "case.is.null"));
        if (StringUtils.isNotBlank(request.getWorkAddress())) {
            PersonalAddress personalAddress = generatePersonalAddress(request, baseCase, userModel, AddressType.COMPANY_ADDR, request.getWorkAddress());
            list.add(personalAddress);
        }
        if (StringUtils.isNotBlank(request.getHomeAddress())) {
            PersonalAddress personalAddress = generatePersonalAddress(request, baseCase, userModel, AddressType.HOUSE_ADDR, request.getHomeAddress());
            list.add(personalAddress);
        }
        if (StringUtils.isNotBlank(request.getCensusAddress())) {
            PersonalAddress personalAddress = generatePersonalAddress(request, baseCase, userModel, AddressType.NATIVE_ADDR, request.getCensusAddress());
            list.add(personalAddress);
        }
        RepositoryUtil.saveData(personalAddressElastic, list);
    }

    /**
     * 生成地址信息
     */
    private PersonalAddress generatePersonalAddress(AddAddressRequest request, BaseCase baseCase, UserModel userModel, AddressType type, String address) {
        PersonalAddress personalAddress = new PersonalAddress();
        personalAddress.setCaseId(request.getCaseId());
        personalAddress.setCaseNumber(baseCase.getCaseNumber());
        personalAddress.setPrincipalId(request.getPrincipalId());
        personalAddress.setCertificateNo(request.getCertificateNo());
        personalAddress.setName(request.getName());
        personalAddress.setSource(request.processSource());
        personalAddress.setRelation(request.processRelation());
        personalAddress.setRemark(request.getRemark());
        personalAddress.setAddressDetail(address);
        personalAddress.setType(type);
//        personalAddress.setStatus(ContactStatus.EFFECTIVE);
        personalAddress.setAssistFlag(BaseSelect.NO);
        personalAddress.process(userModel.getId(), ZWDateUtil.getNowDateTime(), true);
        return personalAddress;
    }

    /**
     * 修改联系人信息
     */
    public void modifyPersonalContact(ModifyContactRequest request, String token) {
        checkCase(request.getCaseId(), request.getCaseType());
        UserModel userModel = baseService.getUserByToken(token);
        PersonalContact personalContact = personalContactElastic.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "personalContact", "personal.contact.is.null"));
        personalContact.setName(request.getName());
        personalContact.setPhoneNo(request.getPhoneNo());
        personalContact.setCertificateNo(request.getCertificateNo());
        personalContact.setRelation(StringUtils.isBlank(request.getRelation().toString()) ? null : request.getRelation());
        personalContact.setRemark(request.getRemark());
        personalContact.setSource(StringUtils.isBlank(request.getSource().toString()) ? null : request.getSource());
        personalContact.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
        personalContactElastic.save(personalContact);
    }

    /**
     * 修改地址信息
     */
    public void modifyPersonalAddress(ModifyAddressRequest request, String token) {
        checkCase(request.getCaseId(), request.getCaseType());
        UserModel userModel = baseService.getUserByToken(token);
        PersonalAddress personalAddress = personalAddressElastic.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "personalAddress", "personal.address.is.null"));
        personalAddress.setCertificateNo(request.getCertificateNo());
        personalAddress.setName(request.getName());
        personalAddress.setRelation(StringUtils.isBlank(request.getRelation().toString()) ? null : request.getRelation());
        personalAddress.setAddressDetail(request.getAddressDetail());
        personalAddress.setSource(StringUtils.isBlank(request.getSource().toString()) ? null : request.getSource());
        personalAddress.setRemark(request.getRemark());
        personalAddress.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
        personalAddressElastic.save(personalAddress);
    }

    /**
     * 删除联系人/地址
     */
    public void deletePersonalContact(String id, Integer type) {
        if (type.equals(0)) {
            personalContactElastic.deleteById(id);
        } else {
            personalAddressElastic.deleteById(id);
        }
    }

    /**
     * 修改备注
     */
    public void modifyRemark(ModifyContactRequest request, String token) {
        checkCase(request.getCaseId(), request.getCaseType());
        UserModel userModel = baseService.getUserByToken(token);
        if (request.getType().equals(0)) {
            PersonalContact personalContact = personalContactElastic.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "personalContact", "personal.contact.is.null"));
            personalContact.setRemark(request.getRemark());
            personalContact.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
            personalContactElastic.save(personalContact);
        } else {
            PersonalAddress personalAddress = personalAddressElastic.findById(request.getId()).orElseThrow(() -> new BadRequestException(null, "personalAddress", "personal.address.is.null"));
            personalAddress.setRemark(request.getRemark());
            personalAddress.process(userModel.getId(), ZWDateUtil.getNowDateTime(), false);
            personalAddressElastic.save(personalAddress);
        }
    }

    /**
     * 判断催收类型是否改变
     */
    private void checkCase(String caseId, CaseType caseType) {
        Optional<CaseInfo> optional = caseInfoRepository.findById(caseId);
        if (!optional.isPresent()) {
            throw new BadRequestException(null, "caseInfo", "case.is.done");
        }
        CaseInfo caseInfo = optional.get();
        if (caseInfo.getCaseDataStatus().equals(CaseDataStatus.PAUSE)) {
            throw new BadRequestException(null, "caseInfo", "case.is.stop");
        }
        if (caseInfo.getCaseDataStatus().equals(CaseDataStatus.SETTLT) || caseInfo.getCaseDataStatus().equals(CaseDataStatus.REDUCE)) {
            throw new BadRequestException(null, "caseInfo", "case.is.clear");
        }
        if (!caseType.equals(caseInfo.getCaseType())) {
            throw new BadRequestException(null, "caseInfo", "case.type.is.change");
        }
        if (caseInfo.getPublicCaseFlag().equals(PublicCaseFlag.PUBLIC_CASE)) {
            throw new BadRequestException(null, "caseInfo", "case.is.public");
        }
    }
}